﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;   
namespace PBCodeGen
{
    public static  class CodeGenManager
    {
        private static  List<string> MessageNames = new List<string>();
        private static List<string> MessageID2Server = new List<string>();
        private static string PackageName;
        private static string ProtoFilePath;

        public static void GenAll(string protoFilePath,string CSharpDefinePath,string CSharpHandlerPath,string GoHandlerPath,string GoDefinePath) 
        {
            ReadProtoMessage(protoFilePath);
            ProtoFilePath = protoFilePath;
            GenCSharp(CSharpDefinePath,CSharpHandlerPath);

            GenGo(GoHandlerPath,GoDefinePath);
        }

        public static void ReadProtoMessage(string protoFilePath) 
        {
            StreamReader stream = new StreamReader(protoFilePath, Encoding.Default);
            string line;
            string preLine = "";
            while ((line = stream.ReadLine()) != null)
            {
                string[] wordArr = line.Split(' ');
                if (wordArr == null && wordArr.Length <= 0) 
                {
                    continue;
                }
                if(wordArr[0]=="message")
                {
                    string MsgName = line.Replace("message", "").Trim();
                    string strId2Server = preLine.Substring(2, preLine.Length - 2).Trim();
                    MessageNames.Add(MsgName);
                    MessageID2Server.Add(strId2Server);
                }

                if (wordArr[0] == "package") 
                {
                    string packetName = line.Replace("package","").Trim();
                    PackageName = packetName;
                }
                preLine = line;
            }
        }

        #region C#
        public static void GenCSharp(string CSharpDefinePath,string CSharpHandlerPath) 
        {
            GenCSharp_MessageID(CSharpDefinePath);
            GenCSharp_HandlerDic(CSharpHandlerPath);
            GenCSharp_Handlers(CSharpHandlerPath);
            GenCSharp_MsgDefine(CSharpDefinePath);
        }

        public static void GenCSharp_MessageID(string CSharpDefinePath) 
        {
            string StrPBMessageIDs =  File.ReadAllText("Templates/PBMessageID.cs");
            string AllMsgStrs  = "";
            for (int i = 0; i < MessageNames.Count;i++ )
            {
                AllMsgStrs += MessageNames[i] + " = "+(i+1).ToString()+",\r\n    ";
            }
            StrPBMessageIDs = StrPBMessageIDs.Replace("$MessageIDs$", AllMsgStrs);
            File.WriteAllText(CSharpDefinePath+"/PBMessageID.cs",StrPBMessageIDs);
        }

        public static void GenCSharp_HandlerDic(string CSharpHandlerPath)   
        {
            string StrHandlers = File.ReadAllText("Templates/PacketHandlersDic.cs");
            string AddHandlerStrs="";
            for(int i=0;i<MessageNames.Count;i++)
            {
                string MsgType = MessageNames[i].Split('_')[0];
                if (MsgType == "SC")
                {
                    AddHandlerStrs += "PBIDMapping " + MessageNames[i] + "Mapping = new PBIDMapping(new " + MessageNames[i] + "_Handler(),typeof(" + MessageNames[i] + "));\r\n    ";
                    AddHandlerStrs += "this.Handlers.Add(PBMessageID." + MessageNames[i] + "," + MessageNames[i] + "Mapping);\r\n    ";
                }
            }
            StrHandlers = StrHandlers.Replace("$AddHandler$", AddHandlerStrs);
            File.WriteAllText(CSharpHandlerPath + "/PacketHandlersDic.cs", StrHandlers);
        }

        public static void GenCSharp_Handlers(string CSharpHandlerPath) 
        {
            string strHandleTemplate = File.ReadAllText("Templates/HandlerTemplate.cs");

            for (int i = 0; i < MessageNames.Count; i++)
            {
                if (!File.Exists(CSharpHandlerPath + @"\" + MessageNames[i] + "_Handler.cs"))
                {
                     string MsgType = MessageNames[i].Split('_')[0];
                     if (MsgType == "SC")
                     {
                         string HandlerStr = strHandleTemplate.Replace("$PacketName$", MessageNames[i]);
                         HandlerStr = "using " + PackageName + "\r\n" + HandlerStr;
                         File.WriteAllText(CSharpHandlerPath + @"\" + MessageNames[i] + "_Handler.cs", HandlerStr);
                     }
                }
            }
        }

        public static void GenCSharp_MsgDefine(string CSharpDefinePath) 
        {
            string[] PathArr = ProtoFilePath.Split('\\');
            string protoName = PathArr[PathArr.Length - 1];
            string protoPath = ProtoFilePath.Replace(protoName,"");
            string GenBatStr = "";
            GenBatStr+= "cd " + protoPath + "\r\n";
            GenBatStr += "protogen -i:" + protoName + " -o:" + protoName + ".cs" + "\r\n";
            GenBatStr += "copy "+ protoName + ".cs "+CSharpDefinePath+"\\"+ protoName + ".cs \r\n" ;
            GenBatStr += "del " + protoName + ".cs \r\n";
            File.WriteAllText("GenCSharp.bat",GenBatStr);
            Process.Start("GenCSharp.bat");
        }
        #endregion


        #region GO
        public static void GenGo(string GoHandlerPath, string GoDefinePath) 
        {
            GenGoMsgId(GoDefinePath);
            //GenGoHandlerDic(GoHandlerPath);
            //GenGoMsgHandlers(GoHandlerPath);
            GenGoMsgDefine(GoDefinePath);
        }

        public static void GenGoMsgId(string GoDefinePath)
        {
          string AllMsgStr = File.ReadAllText("Templates/PBMessageID.go");
          string AllIDsStr = "";
          for (int i = 0; i < MessageNames.Count;i++)
          {
              AllIDsStr += "PBID_"+ MessageNames[i]+" = "+(i+1).ToString()+" \r\n    ";
          }
          AllMsgStr = AllMsgStr.Replace("$MessageIDs$",AllIDsStr);
          
          string AllId2ServerStr = "";
          for (int i = 0; i < MessageID2Server.Count;i++)
          {
              int ServerId = 0;
              switch (MessageID2Server[i])
              {
                  case "HallServer":
                      ServerId = 0;
                  break;
                  case "SceneServer":
                      ServerId = 1;
                  break;
                  case "ChatServer":
                      ServerId = 2;
                  break;
              }
              AllId2ServerStr += "id2Server[PBID_" + MessageNames[i] + "] = " + ServerId.ToString()+"\r\n";
          }
          AllMsgStr = AllMsgStr.Replace("$IDServerMap$",AllId2ServerStr);
          File.WriteAllText(GoDefinePath + @"\" + "PBMessageID.go",AllMsgStr);
        }

        public static void GenGoHandlerDic(string HandlerPath)
        {
            string AllHandlerStr = File.ReadAllText("Templates/PBHandlers.go");
            string AllAddHandlerStr = "";  
            for (int i = 0; i < MessageNames.Count; i++)
            {
               string MsgType = MessageNames[i].Split('_')[0];
               if (MsgType == "CS")
               {
                   AllAddHandlerStr += "PBHandlers.AddHandler(PBMessage.PBID_" + MessageNames[i] + "," + MessageNames[i] + "_Handler) \r\n    ";
               }
            }
            AllHandlerStr = AllHandlerStr.Replace("$AddHandlers$", AllAddHandlerStr);
            File.WriteAllText(HandlerPath + @"\" + "PBHandlers.go", AllHandlerStr);
        }

        public static void GenGoMsgHandlers(string HanlerPath) 
        {
           string TemplateStr = File.ReadAllText("Templates/HandlerTemplate.go");
           for (int i = 0; i < MessageNames.Count; i++)
           {
               if (!File.Exists(HanlerPath + @"\" + MessageNames[i] + "_Handler.go"))
               {
                   string MsgType = MessageNames[i].Split('_')[0];
                   if (MsgType == "CS")
                   {
                       string HandlerStr = TemplateStr.Replace("$PacketName$", MessageNames[i]);
                       File.WriteAllText(HanlerPath + @"\" + MessageNames[i] + "_Handler.go", HandlerStr);
                   }
               }
           }
        }

        public static void GenGoMsgDefine(string DefinePath)
        {
            string[] PathArr = ProtoFilePath.Split('\\');
            string protoName = PathArr[PathArr.Length - 1];
            string protoPath = ProtoFilePath.Replace(protoName, "");
            string GenBatStr = "";
            GenBatStr += "cd " + protoPath + "\r\n";

            GenBatStr += "protoc --go_out=. " + protoName+" \r\n";
            string GenGoName = protoName.Split('.')[0] + ".pb.go";
            GenBatStr += "copy " + GenGoName + " " + DefinePath + "\\" + GenGoName + "\r\n";
            GenBatStr += "del " + GenGoName + "\r\n";
            File.WriteAllText("GenGo.bat", GenBatStr);
            Process.Start("GenGo.bat");
        }
        #endregion

    }
}
